import type { AxiosResponse, CreateAxiosDefaults } from 'axios'
import { useAuthStore } from '@/content/stores/auth'
import { generateSign } from '@/utils/common'
import axios from 'axios'
import { ElMessage } from 'element-plus'

const {
  VITE_PROTOCOL,
  VITE_BASE_URL,
  VITE_MD5_SERVER_SECRET,
} = import.meta.env

type IOptions = CreateAxiosDefaults & {
  responseOriginData?: boolean
}

class ClientAxiosInstanceWrapper {
  private instance

  constructor(option?: IOptions) {
    this.instance = axios.create({
      baseURL: '',
      timeout: 60000,
      ...(option || {}),
    })

    this.instance.interceptors.request.use((config) => {
      return config
    })

    this.instance.interceptors.response.use((res: AxiosResponse) => {
      return res.data
    }, (e) => {
      ElMessage({
        type: 'error',
        message: e.message || '客户端接口请求异常！',
        duration: 3000,
      })
      return Promise.reject(e)
    })
  }

  getInstance() {
    return this.instance
  }
}

class ServerAxiosInstanceWrapper {
  private instance

  constructor(option?: IOptions) {
    this.instance = axios.create({
      baseURL: '',
      timeout: 60000,
      ...(option || {}),
    })

    this.instance.interceptors.request.use((config) => {
      const { token } = useAuthStore()
      if (token) {
        config.headers.Authorization = `Bearer ${token}`
        const version = `${config.url!.split('/').filter(Boolean)[0].toUpperCase()}.000`
        const timestamp = new Date().getTime()
        const sign = generateSign({
          requestParams: config.params,
          requestMethod: config.method!.toUpperCase(),
          version,
          timestamp,
          token,
          secret: VITE_MD5_SERVER_SECRET,
        })

        config.headers.version = version
        config.headers.timestamp = timestamp
        config.headers.sign = sign
      }

      return config
    })

    this.instance.interceptors.response.use((res: AxiosResponse) => {
      if (res.status !== 200) {
        ElMessage({
          type: 'error',
          message: res.data?.msg || '服务器出小差啦！',
          duration: 3000,
        })
        Promise.reject(new Error(res.data?.msg || '服务器出小差啦！'))
        return
      }

      if (!option?.responseOriginData && res.data?.http_status !== 200) {
        ElMessage({
          type: 'error',
          message: res.data?.msg || '服务器出小差啦！',
          duration: 3000,
        })
        Promise.reject(new Error(res.data?.msg || '服务器出小差啦！'))
        return
      }

      return option?.responseOriginData ? res : res.data.result
    }, (e) => {
      if (e.status === 401) {
        const authStore = useAuthStore()
        authStore.deleteToken()
        ElMessage({
          type: 'error',
          message: '登录已过期，请重新登录！',
          duration: 3000,
        })
        setTimeout(() => {
          window.location.href = ''
        }, 2000)
        return
      }

      ElMessage({
        type: 'error',
        message: e.response?.data?.msg ?? '服务器出小差啦！',
        duration: 3000,
      })
      return Promise.reject(e)
    })
  }

  getInstance() {
    return this.instance
  }
}

export function getClientHttp(option?: IOptions) {
  return new ClientAxiosInstanceWrapper(option).getInstance()
}

export function getServerHttp(option?: IOptions) {
  const instance = new ServerAxiosInstanceWrapper({
    baseURL: VITE_PROTOCOL + VITE_BASE_URL,
    ...(option || {}),
  }).getInstance()

  instance.defaults.headers.post['Content-Type'] = 'application/json'

  return instance
}
